package com.yw.android.common.utils;

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

/**
 * 线程执行器
 *
 * @author yuanwei
 */
public class Executor {
    private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
    private static final int CORE_POOL_SIZE = CPU_COUNT + 1;

    /**
     * 线程执行器
     */
    private static ScheduledExecutorService executor = null;

    /**
     * 初始化线程执行器
     */
    static {
        executor = Executors.newSingleThreadScheduledExecutor();
    }

    /**
     * 安全启动线程
     *
     * @param runnable 要执行的功能
     * @param delay    从现在开始延迟执行的时间
     * @param unit     延迟参数的时间单位
     * @return 可用于提取结果或取消的ScheduledFuture
     */
    public static ScheduledFuture<?> schedule(Runnable runnable, long delay, TimeUnit unit) {
        if (executor.isShutdown() || executor.isTerminated()) {
            LOG.e("[executor:" + executor.hashCode()
                    + "] executor is shutdown, schedule failed");
            return null;
        } else {
            return executor.schedule(runnable, delay, unit);
        }
    }

    /**
     * 安全启动线程
     *
     * @param runnable 要执行的功能
     */
    public static void execute(Runnable runnable) {
        if (executor.isShutdown() || executor.isTerminated()) {
            LOG.e("[executor:" + executor.hashCode()
                    + "] executor is shutdown, execute failed");
        } else {
            executor.execute(runnable);
        }
    }

    /**
     * 捕获异常的执行类
     *
     * @author yuanwei
     */
    public static abstract class RunNoThrowable implements Runnable {
        /**
         * 上下文参数，当抛出异常时用于打印前后环境数据
         */
        private String env = null;

        /**
         * 构造函数
         */
        public RunNoThrowable() {
            this("[unknown]");
        }

        /**
         * 构造函数
         *
         * @param env 上下文参数，当抛出异常时用于打印前后环境数据
         */
        public RunNoThrowable(String env) {
            this.env = env;
        }

        @Override
        public final void run() {
            try {
                rundo();
            } catch (Throwable e) {
                LOG.e(env + " rundo failed(Throwable)", e);
            }
        }

        /**
         * 执行对象，需要重载，执行过程中抛出的任何异常都会被捕获
         */
        public abstract void rundo();
    }
}
